package me.jayramafisher.mcsurvival;

import org.jnbt.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

//File: NBTManager.java
//Description: static class to provide funtions related to NBT objects.
//Last date of modification (yyyymmdd): 20110716

/**
*The NBTManager class is a static class that provides utility methods for operating on NBT files and objects.
*/

public class NBTManager
{

    //static class, not to be instantiated
    private NBTManager() {}
	
	public static Tag load(File file) throws Exception
        {
	    NBTInputStream in = new NBTInputStream(new FileInputStream(file));
	    Tag result = in.readTag();
		in.close();
		return result;
	}
	
	public static void save(File file, Tag tag) throws Exception
        {
	    NBTOutputStream out = new NBTOutputStream(new FileOutputStream(file));
	    out.writeTag(tag);
		out.close();
	}
	
	//access objects down the nbt compound tree with period delimited subtags
	public static Tag getTag(CompoundTag root, String address) throws Exception
        {
	    address = address.trim();
		if(address.equals("")) return root;
		String[] split = address.split("\\.");
		if(!root.getValue().containsKey(split[0])) throw new Exception("Error: NBT node not found.");
		return getTag((CompoundTag)root.getValue().get(split[0]),address.substring(address.indexOf('.')+1,address.length()));
	}
	
	public static CompoundTag getCompoundTag(CompoundTag root, String address) throws Exception
        {
	    Tag tag = getTag(root,address);
		if(!(tag instanceof CompoundTag)) throw new Exception("Error: tag requested was not a CompoundTag.");
		return (CompoundTag)tag;
	}
	
	public static byte[] getByteArray(CompoundTag root, String address) throws Exception
        {
	    Tag tag = getTag(root,address);
		if(!(tag instanceof ByteArrayTag)) throw new Exception("Error: tag requested was not a byte array.");
		return ((ByteArrayTag)tag).getValue();
	}
	
	public static double getDouble(CompoundTag root, String address) throws Exception
        {
	    Tag tag = getTag(root,address);
		if(!(tag instanceof DoubleTag)) throw new Exception("Error: tag requested was not a double.");
		return ((DoubleTag)tag).getValue();
	}
	
	public static float getFloat(CompoundTag root, String address) throws Exception
        {
	    Tag tag = getTag(root,address);
		if(!(tag instanceof FloatTag)) throw new Exception("Error: tag requested was not a float.");
		return ((FloatTag)tag).getValue();
	}
	
	public static int getInt(CompoundTag root, String address) throws Exception
        {
	    Tag tag = getTag(root,address);
		if(!(tag instanceof IntTag)) throw new Exception("Error: tag requested was not a int.");
		return ((IntTag)tag).getValue();
	}
	
	public static long getLong(CompoundTag root, String address) throws Exception
        {
	    Tag tag = getTag(root,address);
		if(!(tag instanceof LongTag)) throw new Exception("Error: tag requested was not a long.");
		return ((LongTag)tag).getValue();
	}
	
	public static short getShort(CompoundTag root, String address) throws Exception
        {
	    Tag tag = getTag(root,address);
		if(!(tag instanceof ShortTag)) throw new Exception("Error: tag requested was not a short.");
		return ((ShortTag)tag).getValue();
	}
	
	public static String getString(CompoundTag root, String address) throws Exception
        {
	    Tag tag = getTag(root,address);
		if(!(tag instanceof StringTag)) throw new Exception("Error: tag requested was not a String.");
		return ((StringTag)tag).getValue();
	}
	
	public static List<Tag> getList(CompoundTag root, String address) throws Exception
        {
	    Tag tag = getTag(root,address);
		if(!(tag instanceof ListTag)) throw new Exception("Error: tag requested was not a List.");
		return ((ListTag)tag).getValue();
	}
	
	//access objects down the nbt compound tree with period delimited subtags
	public static void setTag(CompoundTag root, String address, Tag value) throws Exception
        {
	    address = address.trim();
		String[] split = address.split("\\.");
		if(split.length == 0);
		else if(split.length == 1) root.getValue().put(split[0],value);
		else {
		    if(!root.getValue().containsKey(split[0])) {
			    Map<String,Tag> map = new TreeMap<String,Tag>();
			    CompoundTag sub = new CompoundTag(split[0],map);
				setTag(sub,address.substring(address.indexOf("\\.")+1,address.length()),value);
			}
			else if(!(root.getValue().get(split[0]) instanceof CompoundTag)) throw new Exception("Error: NBT node was not a CompoundTag.");
			else setTag((CompoundTag)root.getValue().get(split[0]),address.substring(address.indexOf("\\.")+1,address.length()),value);
		}
	}
	
	public static void setCompoundTag(CompoundTag root, String address, CompoundTag value) throws Exception
        {
	    setTag(root,address,value);
	}
	
	public static void setByteArray(CompoundTag root, String address, byte[] value) throws Exception
        {
	    setTag(root,address,new ByteArrayTag(address.substring(address.lastIndexOf("\\.")),value));
	}
	
	public static void setDouble(CompoundTag root, String address, double value) throws Exception
        {
	    setTag(root,address,new DoubleTag(address.substring(address.lastIndexOf("\\.")),value));
	}
	
	public static void setFloat(CompoundTag root, String address, float value) throws Exception
        {
	    setTag(root,address,new FloatTag(address.substring(address.lastIndexOf("\\.")),value));
	}
	
	public static void setInt(CompoundTag root, String address, int value) throws Exception
        {
	    setTag(root,address,new IntTag(address.substring(address.lastIndexOf("\\.")),value));
	}
	
	public static void setLong(CompoundTag root, String address, long value) throws Exception
        {
	    setTag(root,address,new LongTag(address.substring(address.lastIndexOf("\\.")),value));
	}
	
	public static void setShort(CompoundTag root, String address, short value) throws Exception
        {
	    setTag(root,address,new ShortTag(address.substring(address.lastIndexOf("\\.")),value));
	}
	
	public static void setString(CompoundTag root, String address, String value) throws Exception
        {
	    setTag(root,address,new StringTag(address.substring(address.lastIndexOf("\\.")),value));
	}
	
	public static void setList(CompoundTag root, String address, List<Tag> value) throws Exception
        {
	    setTag(root,address,new ListTag(address.substring(address.lastIndexOf("\\.")),
            value.size() == 0 ?
                NBTUtils.getTypeClass(1) :
                value.get(0).getClass()
        ,value));
	}

}










